<template>
    <div class="control-container" v-if="touchable">
        <div v-if="settings.close.enabled" ref="close" class="close" :class="[settings.close.hor, settings.close.ver]" @click="toggle" @touchstart.prevent="toggle">
            <i class="fa fa-fw fa-close" v-if="shown"></i>
            <i class="fa fa-fw fa-arrows" v-else=""></i>
        </div>
        <div ref="control" class="control" :class="{ half: !(settings.x || settings.y || settings.a || settings.b) }" :style="space" v-show="shown" @touchstart.prevent="tip" @click="tip">
            <div class="direction">
                <div v-if="settings.fixed">
                    <div class="vertical" v-if="settings.directions === 'vertical'">
                        <div><i class="fa fa-fw fa-chevron-up"></i></div>
                        <div><i class="fa fa-fw fa-chevron-down"></i></div>
                    </div>
                    <div class="horizontal" v-if="settings.directions === 'horizontal'">
                        <div><i class="fa fa-fw fa-chevron-left"></i></div>
                        <div><i class="fa fa-fw fa-chevron-right"></i></div>
                    </div>
                    <div class="four" v-if="settings.directions === 'four'">
                        <div><i class="fa fa-fw fa-chevron-up"></i></div>
                        <div><i class="fa fa-fw fa-chevron-down"></i></div>
                        <div><i class="fa fa-fw fa-chevron-left"></i></div>
                        <div><i class="fa fa-fw fa-chevron-right"></i></div>
                    </div>
                    <div class="eight" v-if="settings.directions === 'eight'"></div>
                    <div class="full" v-if="settings.directions === 'full'"></div>
                </div>
                <div v-else="" ref="free" id="free" @touchstart.stop="freeStart" @touchmove.stop="freeMove" @touchend.stop="freeEnd">
                    <div class="area">
                        <div class="bg" :class="[ settings.directions ]">
                            <div class="up" :class="{ active: touch === 'up' }" v-if="settings.directions === 'eight' || settings.directions === 'four' || settings.directions === 'vertical'"><i class="fa fa-fw fa-chevron-up"></i></div>
                            <div class="right" :class="{ active: touch === 'right' }" v-if="settings.directions === 'eight' || settings.directions === 'four' || settings.directions === 'horizontal'"><i class="fa fa-fw fa-chevron-right"></i></div>
                            <div class="down" :class="{ active: touch === 'down' }" v-if="settings.directions === 'eight' || settings.directions === 'four' || settings.directions === 'vertical'"><i class="fa fa-fw fa-chevron-down"></i></div>
                            <div class="left" :class="{ active: touch === 'left' }" v-if="settings.directions === 'eight' || settings.directions === 'four' || settings.directions === 'horizontal'"><i class="fa fa-fw fa-chevron-left"></i></div>

                            <div class="upright" :class="{ active: touch === 'upright' }" v-if="settings.directions === 'eight'"><i class="fa fa-fw fa-chevron-up fa-rotate-45"></i></div>
                            <div class="downright" :class="{ active: touch === 'downright' }" v-if="settings.directions === 'eight'"><i class="fa fa-fw fa-chevron-up fa-rotate-135"></i></div>
                            <div class="downleft" :class="{ active: touch === 'downleft' }" v-if="settings.directions === 'eight'"><i class="fa fa-fw fa-chevron-up fa-rotate-225"></i></div>
                            <div class="upleft" :class="{ active: touch === 'upleft' }" v-if="settings.directions === 'eight'"><i class="fa fa-fw fa-chevron-up fa-rotate-315"></i></div>
                        </div>
                        <div class="handle"></div>
                    </div>
                </div>
            </div>
            <div class="buttons" v-if="settings.x || settings.y || settings.a || settings.b" :class="settings.layer" :style="{ 'pointer-events': settings.x || settings.y || settings.a || settings.b ? 'auto' : 'none' }" @touchstart.prevent="tip" @click="tip">
                <div class="button" :class="{ column: !settings.x && !settings.y, row: !settings.b, [settings.locations.a]: true }" v-if="settings.a" @touchstart.stop="start('a')" @touchend.stop="end('a')" @click.stop="press('a')">A</div>
                <div class="button" :class="{ column: !settings.x && !settings.y, row: !settings.a, [settings.locations.b]: true }" v-if="settings.b" @touchstart.stop="start('b')" @touchend.stop="end('b')" @click.stop="press('b')">B</div>
                <div class="button" :class="{ column: !settings.a && !settings.b, row: !settings.y, [settings.locations.x]: true }" v-if="settings.x" @touchstart.stop="start('x')" @touchend.stop="end('x')" @click.stop="press('x')">X</div>
                <div class="button" :class="{ column: !settings.a && !settings.b, row: !settings.x, [settings.locations.y]: true }" v-if="settings.y" @touchstart.stop="start('y')" @touchend.stop="end('y')" @click.stop="press('y')">Y</div>
            </div>
        </div>
    </div>
</template>
<script>
    import extend from 'extend';
    import { utils } from './../../../client';

    export default {
        props: {
            config: {
                required: false,
                type: Object,
                default: () => ({})
            }
        },
        computed: {
            space() {
                let space = this.config.space || { };
                if (typeof space.top !== 'undefined' && typeof space.bottom !== 'undefined' && typeof space.height === 'undefined') {
                    space.height = 'auto';
                }
                return space;
            }
        },
        data() {
            return {
                shown: true,
                touchable: utils.touchable,
                touch: 'none',
                tipTimer: false,
                settings: {
                    a: false,
                    b: false,
                    x: false,
                    y: false,
                    layer: 'square', //skew(倾斜), square(方正)
                    locations: {
                        a: 'a',
                        b: 'b',
                        x: 'x',
                        y: 'y'
                    },
                    directions: 'full', //full(无极), eight(八方向), four(四方向), vertical(上下), horizontal(左右)
                    fixed: false,
                    close: {
                        enabled: true,
                        ver: 'top',
                        hor: 'right'
                    }
                },
                size: {
                    free: {
                        width: 0,
                        height: 0
                    },
                    area: {
                        size: 0,
                        half: 0
                    },
                    handle: {
                        size: 0,
                        half: 0
                    }
                },
                timer: 0
            }
        },
        mounted() {
            this.settings = extend(true, this.settings, this.config);
            this.$nextTick(() => {
                this.$free = $(this.$refs.free);
                this.$area = this.$free.find('.area');
                this.$handle = this.$area.find('.handle');
                this.setSize();
                $(window).on('resize', this.setSize);
            });
        },
        beforeDestory() {
            $(window).off('resize', this.setSize);
        },
        methods: {
            setSize() {
                this.size.free.width = Math.ceil(this.$free.width());
                this.size.free.height = Math.ceil(this.$free.height());
                this.size.area.size = Math.ceil(this.$area.width());
                this.size.area.half = Math.ceil(this.size.area.size / 2);
                this.size.handle.size = Math.ceil(this.$handle.width());
                this.size.handle.half = Math.ceil(this.size.handle.size / 2);
            },
            freeStart(event) {
                let point = utils.point(event, this.$free);
                this.$area.css({ left: Math.max(0, Math.min(this.size.free.width - this.size.area.size, point.x - this.size.area.half)), top: Math.max(0, Math.min(this.size.free.height - this.size.area.size, point.y - this.size.area.half)) });
                point = utils.point(event, this.$area);
                this.changePoint(point);
            },
            freeMove(event) {
                this.changePoint(utils.point(event, this.$area));
            },
            freeEnd() {
                if (this.touch !== 'none') {
                    this.$root.$emit('control.end', { name: this.touch });
                }
                this.touch = 'none';
                this.$area.css({ left: 0, top: this.size.free.height - this.size.area.size });
                this.$handle.css({ left: this.size.area.half - this.size.handle.half, top: this.size.area.half - this.size.handle.half });
                clearTimeout(this.timer);
            },
            changePoint({ x, y }) {
                let areaHalf = this.size.area.half;
                let handleHalf = this.size.handle.half;
                x = x - areaHalf;
                y = y - areaHalf;
                let l2 = x * x + y * y;
                if (l2 >= handleHalf * handleHalf) {
                    let touch = this.getTouch({ x, y });
                    if (this.touch !== touch) {
                        if (this.touch !== 'none') {
                            this.$root.$emit('control.end', { name: this.touch });
                        }
                        if (touch !== 'none') {
                            this.$root.$emit('control.start', { name: touch });
                        }
                        this.touch = touch;
                    }
                }
                clearTimeout(this.timer);
                this.timer = setTimeout(() => {
                    let l = Math.sqrt(l2);
                    let r = areaHalf - handleHalf;
                    if (l > r) {
                        this.$handle.css({ left: x * r / l + r, top: y * r / l + r });
                    } else {
                        this.$handle.css({ left: x + r, top: y + r });
                    }
                });
            },
            getTouch({ x, y }) {
                switch (this.settings.directions) {
                    case 'full': return x === 0 && y === 0 ? 'none' : (y > 0 ? Math.atan2(-y, x) + 2 * Math.PI : Math.atan2(-y, x));
                    case 'eight': if (x === 0 && y === 0) return 'none'; let angle = (utils.asDeg((y > 0 ? Math.atan2(-y, x) + 2 * Math.PI : Math.atan2(-y, x))) + 22.5) % 360; console.log(angle); return angle <= 45 ? 'right' : angle <= 90 ? 'upright' : angle <= 135 ? 'up' : angle <= 180 ? 'upleft' : angle <= 225 ? 'left' : angle <= 270 ? 'downleft' : angle <= 315 ? 'down' : angle <= 360 ? 'downright' : 'none';
                    case 'four': return Math.abs(x) < Math.abs(y) ? y > 0 ? 'down' : y < 0 ? 'up' : 'none' : Math.abs(x) > Math.abs(y) ? x > 0 ? 'right' : x < 0 ? 'left' : 'none' : 'none';
                    case 'vertical': return y < 0 ? 'up' : y > 0 ? 'down' : 'none';
                    case 'horizontal': return x > 0 ? 'right' : x < 0 ? 'left' : 'none';
                }
                return 'none';
            },
            start(name) {
                this.$root.$emit('control.start', { name });
            },
            end(name) {
                this.$root.$emit('control.end', { name });
            },
            press(name) {
                this.$root.$emit('control.press', { name });
            },
            show() {
                this.shown = true;
            },
            hide() {
                this.shown = false;
            },
            tip() {
                $(this.$refs.close).addClass('flash_tip');
                clearTimeout(this.tipTimer);
                this.tipTimer = setTimeout(() => {
                    $(this.$refs.close).removeClass('flash_tip');
                }, 500);
            },
            toggle() {
                this.shown = !this.shown;
            }
        }
    }
</script>